package com.kersci.heartratereader

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattService
import android.content.Intent
import android.content.pm.ActivityInfo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.PowerManager
import android.os.SystemClock
import android.view.View
import android.view.Window
import android.view.WindowManager
import com.clj.fastble.BleManager
import com.clj.fastble.utils.HexUtil
import com.kersci.heartratereader.utils.HeartRateDeviceConnectEvent
import com.safframework.log.L
import kotlinx.android.synthetic.main.activity_device.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.min

class DeviceActivity : AppCompatActivity() {
    private var deviceName = ""
    private var deviceMac = ""
    private var position = -1
    private var notifySeconds = 0L
    private var maxHeartRateValue = 0
    private var minHeartRateValue = 0

    private lateinit var bluetoothGatt: BluetoothGatt
    private lateinit var heartRateService: BluetoothGattService
    private lateinit var characteristic: BluetoothGattCharacteristic
    private lateinit var wakeLock: PowerManager.WakeLock

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_device)
        supportActionBar?.hide()

        var window = this.window
        window.setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        heartRateLayout.visibility = View.INVISIBLE

        val callIntent = this.intent
        position = callIntent.getIntExtra(BleDeviceService.KEY_DEVICE_POSITION, -1)
        if (position != -1) {
            val intent = Intent(this, BleDeviceService::class.java)
            intent.action = BleDeviceService.ACTION_START_CONNECT
            intent.putExtra(BleDeviceService.KEY_DEVICE_POSITION, position)
            startService(intent)
        }
    }

    @Subscribe(threadMode = ThreadMode.ASYNC, sticky = true)
    fun handleConnectEvent(event: HeartRateDeviceConnectEvent) {
        var eventMsg = ""
        when(event.eventId) {
            HeartRateDeviceConnectEvent.EVENT_CONNECT_FAIL -> {
                eventMsg = "CONNECT_FAIL => "
            }
            HeartRateDeviceConnectEvent.EVENT_CONNECTED -> {
                eventMsg = "CONNECTED => "
            }
            HeartRateDeviceConnectEvent.EVENT_NOTIFY_DATA_CHANGED -> {
                eventMsg = "DATA CHANGED"
            }
        }

        eventMsg += " device: " + event.device?.name
        L.d(eventMsg)

        EventBus.getDefault().removeStickyEvent(event)

        when(event.eventId) {
            HeartRateDeviceConnectEvent.EVENT_CONNECT_FAIL -> {
                finish()
            }

            HeartRateDeviceConnectEvent.EVENT_CONNECTED -> {
                val device = event.device
                if (device != null) {
                    deviceName = device.name
                    deviceMac = device.mac

                    bluetoothGatt = BleManager.getInstance().getBluetoothGatt(device)
                    heartRateService = bluetoothGatt.getService(UUID.fromString(BleDeviceService.UUID_HRM_SERVICE))
                    for (character in heartRateService.characteristics){
                        val charaProp = character.properties
                        if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
                            L.d(character.uuid.toString())
                            characteristic = character
                            requestDataNotify()
                            notifySeconds = SystemClock.elapsedRealtime()
                        }
                    }
                    showHeartRateDeviceInfo()
                }
            }

            HeartRateDeviceConnectEvent.EVENT_NOTIFY_DATA_CHANGED -> {
                val heartRate = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1)
                L.d(HexUtil.formatHexString(characteristic.value, true))
                L.d("Heart Rate => $heartRate")
                runOnUiThread(Runnable {
                    heartStatusImage.visibility = View.INVISIBLE
                    heartStatusImage.postDelayed(Runnable {
                        heartStatusImage.visibility = View.VISIBLE
                    }, 500)

                    heartRateValue.text = heartRate.toString()
                    if (maxHeartRateValue == 0 && minHeartRateValue == 0) {
                        maxHeartRateValue = heartRate
                        minHeartRateValue = heartRate
                    }

                    if (heartRate > maxHeartRateValue) {
                        maxHeartRateValue = heartRate
                    }

                    if (heartRate < minHeartRateValue) {
                        minHeartRateValue = heartRate
                    }

                    maxHeartRate.text = "H. $maxHeartRateValue"
                    minHeartRate.text = "L. $minHeartRateValue"

                    var curr = SystemClock.elapsedRealtime()
                    var timeLength = (curr - notifySeconds) / 1000
                    val hour = timeLength/3600
                    val minute = timeLength%3600/60
                    val second = timeLength%60
                    readTime.text = String.format("%02d:%02d:%02d", hour, minute, second)

                    val dateFormat = SimpleDateFormat("hh:mm:ss")
                    var strTime = dateFormat.format(Date())
                    currentTime.text = strTime
                })
            }
        }
    }

    private fun requestDataNotify() {
        val intent = Intent(this, BleDeviceService::class.java)
        intent.action = BleDeviceService.ACTION_START_NOTIFY
        intent.putExtra(BleDeviceService.KEY_DEVICE_POSITION, position)
        startService(intent)
    }
    private fun showHeartRateDeviceInfo() {
        heartRateLayout.post( Runnable {
            heartRateLayout.visibility = View.VISIBLE
            progressBar.visibility = View.INVISIBLE
            deviceInfo.text = deviceName
        })
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    private fun stopBleOperation() {
        val intent = Intent(this, BleDeviceService::class.java)
        intent.action = BleDeviceService.ACTION_STOP_OPERATION
        intent.putExtra(BleDeviceService.KEY_DEVICE_POSITION, position)
        startService(intent)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
        stopBleOperation()
    }
}